<template>
  <div class="music-audio-wrap">
    <header>
      <div class="header-iconback" @click="back">
        <span class="icon-左箭头"></span>
      </div>
      <div class="header-title">
        <span class="header-music-name">
          {{ nowMusic.nowName }}
        </span>
        <artists :artists="nowMusic.nowArtists" fontColor="white"></artists>
      </div>
    </header>
    <div class="bar-line"></div>
    <section class="music-main">
      <img src="../../assets/imgs/stick_bg.png" class="music-main-stick" />
      <div class="music-main-pic">
        <img v-lazy="nowMusic.nowImgUrl" />
      </div>
    </section>
    <section class="music-section-icon">
      <span class="icon-aixin"></span>
      <span class="icon-comment" @click="getComment"></span>
      <span class="icon-省略"></span>
    </section>
    <section class="music-section-time">
      <span
        >{{ currentTimeInfo.currentMin }}:{{ currentTimeInfo.currentSec }}</span
      >
      <mu-slider
        v-model="currentTimeInfo.value1"
        class="slider"
        @change="setProgress"
      ></mu-slider>
      <span>{{ fullTimeInfo.fullMin }}:{{ fullTimeInfo.fullSec }}</span>
    </section>
    <div class="lyric-content">
      <span v-for="(item, index) of lyricItems" :key="index">
        <span
          v-if="
            currentTimeInfo.currentMin >= item.currentMin &&
            currentTimeInfo.currentSec >= item.currentSec &&
            currentTimeInfo.currentSec <= lyricItems[index + 1].currentSec &&
            currentTimeInfo.currentMin <= lyricItems[index + 1].currentMin
          "
        >
          {{ item.lyric }}
        </span>
      </span>
    </div>
    <section class="music-section-contro">
      <span v-for="item of playModelList" :key="item.key">
        <span class="play-model-icon"
          :class="[item.icon, playModel === item.key ? 'active' : '']"
          @click="changePlayModel(item)"
        ></span>
      </span>
      <span class="icon-prewmusic" @click="prew"></span>
      <span class="icon-pause" @click="play(false)" v-if="isPlaying"></span>
      <span class="icon-play" @click="play(true)" v-else></span>
      <span class="icon-next" @click="next"></span>
      <span class="icon-list" @click="openBottomSheet"></span>
    </section>
    <mu-bottom-sheet :open="bottomSheetShow" @close="closeBottomSheet">
      <mu-list :value="nowMusic && nowMusic.id" @itemClick="closeBottomSheet">
        <mu-sub-header> 播放列表({{ musicUrlList.length }}) </mu-sub-header>
        <mu-list-item
          v-for="(item, index) of musicUrlList"
          :key="item.id"
          :value="item.id"
          class="demo-list"
          @click.native="changeMusic(index, item.id)"
        >
        <mu-list-item-title>{{item.name + ' - ' + (item.artists && item.artists[0] && item.artists[0].name || '佚名')}}</mu-list-item-title>
        <mu-list-item-action>
            <mu-icon value="ic_close" @click="deleteMusic(item.id)" slot="right" />
        </mu-list-item-action>
        </mu-list-item>
      </mu-list>
    </mu-bottom-sheet>
    <div class="mask">
      <div
        class="music-bg"
        :style="{
          'background-image':
            'url(' + nowMusic.nowMusicUrl + '?param=500y500' + ')',
        }"
      ></div>
    </div>
  </div>
</template>

<script lang="ts">
import { namespace } from "vuex-class";
import { Vue, Component, Watch } from "vue-property-decorator";
import Router, { Route } from "vue-router";
import { MusicInfo } from "@/model/music-info.model";
import { CurrentMusic } from "@/model/current-music.model";
import { CurrentTimeInfo, FullTimeInfo } from "@/model/playing-info.model";
import { CommentType, CommonIdType, PlayModel } from "@/model/id-or-enum.model";
import { APIType } from "@/api";
import { CommentHeader } from "@/model/common-header.model";
import { AudioAction } from "@/utils/event";
import { Message } from "element-ui";
const AppModule = namespace("app");
@Component({})
export default class MusicComponent extends Vue {
  bottomSheetShow = false;
  // 歌词
  lyric = "";
  lyricItems: Array<{
    /**时间 */
    date: any;
    // 时间中的分钟数
    currentMin: string;
    // 时间中的秒数(尾数)
    currentSec: string;
    /**歌词内容 */
    lyric: string;
  }> = [];

  playModelList = [
    {
      key: PlayModel.Sequence,
      icon: "icon-列表循环",
      name: "列表循环",
    },
    {
      key: PlayModel.Random,
      icon: "icon-随机播放",
      name: "随机播放",
    },
    {
      key: PlayModel.Single,
      icon: "icon-singlecycle",
      name: "单曲循环",
    },
  ];

  @AppModule.State("nowMusic")
  nowMusic: CurrentMusic;
  @AppModule.State("current")
  currentTimeInfo: CurrentTimeInfo;
  @AppModule.State("full")
  fullTimeInfo: FullTimeInfo;
  @AppModule.State("isPlaying")
  isPlaying: boolean;
  @AppModule.State("playModel")
  playModel: PlayModel;
  @AppModule.State("musicUrlList")
  musicUrlList: MusicInfo[];

  @AppModule.Mutation("setShowController")
  setShowController: (value: boolean) => void;
  @AppModule.Mutation("setPlayModel")
  setPlayModel: (mode: PlayModel) => void;
  @AppModule.Mutation("setIsPlaying")
  setIsPlaying: (value: boolean) => void;
  @AppModule.Mutation("setCurrentMusicInfo")
  setCurrentMusicInfo: (info: CurrentMusic) => void;
  @AppModule.Mutation("setCommentType")
  setCommentType: (type: CommentType) => void;
  @AppModule.Mutation("setCommentHeader")
  setCommentHeader: (header: CommentHeader) => void;
  @AppModule.Mutation("deleteFromMusicList")
  deleteFromMusicList: (id: CommonIdType) => void;
  @AppModule.Mutation("clearCurrentMusicInfo")
  clearCurrentMusicInfo: () => void;

  $api: APIType;
  $route: Route;
  $router: Router;

  public mounted() {
    this.play(false);
    this.getLyric(this.nowMusic?.id ?? this.$route.params.id);
    // console.log(this.lyric)
  }
  // 导航进入评论页面后，隐藏底部音乐控制器
  beforeRouteEnter(to: Route, from: Route, next: (call?: any) => void): void {
    next((vm: MusicComponent) => {
      vm.setShowController(false);
    });
  }
  // 导航进入评论页面后，显示底部音乐控制器
  beforeRouteLeave(to: Route, from: Route, next: (callback?: any) => void) {
    this.setShowController(true);
    next();
  }
  // 监测路由变化，变化则更新歌词
  @Watch("$route")
  private onRouteChange(to: Route, from: Route) {
    this.getLyric(this.nowMusic.id);
  }
  // 改变播放模式
  changePlayModel(mode: {key: PlayModel, name: string}) {
    this.setPlayModel(mode.key);
    Message({
      showClose: true,
      message: mode.name,
      type: 'success'
    });
  }
  // 播放暂停
  play(value: boolean) {
    AudioAction.next({ isPlaying: value });
  }
  // 上一首
  prew() {
    if (!this.musicUrlList.length) {
      this.clearCurrentMusicInfo();
      return;
    }
    let index = 0;
    // 获得下一首歌曲的id
    let id: CommonIdType = 0;
    if (
      this.playModel === PlayModel.Sequence ||
      this.playModel === PlayModel.Single
    ) {
      // 如果是歌曲的第一首，则ind为音乐列表长度减一，以便下次取到的是最后一首
      const nowIndex = this.musicUrlList.findIndex(x => x.id === this.nowMusic?.id);
      index = nowIndex === 0 ? this.musicUrlList.length - 1 : nowIndex - 1;
      id = this.musicUrlList[index].id;
    } else {
      index = Math.floor(Math.random() * this.musicUrlList.length);
      id = this.musicUrlList[index].id;
    }
    // 由于获取的歌单，没有歌曲的url，需要先ajax请求url，再发送
    this.$api.getMusicUrl(id).then((musicList) => {
      // 下一首歌曲的url
      const url = musicList[0].url;
      const { name, artists, imgUrl } = this.musicUrlList[index];
      const info: CurrentMusic = {
        id,
        index,
        nowMusicUrl: url,
        nowName: name,
        nowArtists: artists,
        nowImgUrl: imgUrl,
      };
      this.$router.replace({ path: `/music/${id}` });
      this.setIsPlaying(true);
      this.setCurrentMusicInfo(info);
    });
  }
  next() {
    let index = 0;
    if (!this.musicUrlList.length) {
      this.clearCurrentMusicInfo();
      return;
    }
    // 获得下一首歌曲的id
    let id: CommonIdType = 0;
    if (
      this.playModel === PlayModel.Sequence ||
      this.playModel === PlayModel.Single
    ) {
      // 如果是歌曲的最后一首，则ind为0，以便下次取到的是第一首
      const nowIndex = this.musicUrlList.findIndex(x => x.id === this.nowMusic?.id);
      index = nowIndex === this.musicUrlList.length - 1 ? 0 : nowIndex + 1;
      id = this.musicUrlList[index].id;
    } else {
      index = Math.floor(Math.random() * this.musicUrlList.length);
      id = this.musicUrlList[index].id;
    }
    // console.log(this.musicUrlList[ind].name)
    // 由于获取的歌单，没有歌曲的url，需要先ajax请求url，再发送
    // console.log(index)
    this.$api.getMusicUrl(id).then((musicList) => {
      // 下一首歌曲的url
      const url = musicList[0].url;
      const { name, artists, imgUrl } = this.musicUrlList[index];
      const info: CurrentMusic = {
        id,
        index,
        nowMusicUrl: url,
        nowName: name,
        nowArtists: artists,
        nowImgUrl: imgUrl,
      };
      this.$router.replace({ path: `/music/${id}` });
      this.setIsPlaying(true);
      this.setCurrentMusicInfo(info);
    });
  }
  // 前往评论页面
  getComment() {
    // console.log('go comment')
    let header: CommentHeader = {
      name: this.nowMusic.nowName,
      artists: this.nowMusic.nowArtists,
      musicpic: this.nowMusic.nowMusicUrl,
    };
    this.setCommentType(CommentType.ToSong);
    this.setCommentHeader(header);
    this.$router.push({ path: `/comment/${this.nowMusic.id}` }).catch((err) => err);
  }
  // 获取歌词
  getLyric(id: CommonIdType) {
    const dateReg = /\[\d*:\d*((\.|\:)\d*)*\]/g;
    const result = this.$api.getLyric(id).then((res) => {
      this.lyric = res.lrc.lyric;
      // 获得的歌词是一个字符串，类似'[00:00:00] 歌词第一句/n[00:01:01] 歌词第二句/n'这种
      // 切割成一个数组，数组的每一项包含对应的时间和歌词
      const lyrics = this.lyric.split("\n");
      // 定义一个空数组，用来存放歌词，数组的每一项都是一个对象，对象包含时间属性和歌词属性
      for (let index = 0; index < lyrics.length; index++) {
        let lyric = lyrics[index];
        // 正则匹配，获得包含时间的字符串，
        const eachtime = lyric?.match(dateReg);
        let min = eachtime ? eachtime[0].slice(1, 3) : undefined;
        let sec = eachtime ? eachtime[0].slice(4, 6) : undefined;
        // 将包含时间的字符串替换点，获得对应每一项的歌词
        const eachlyric = lyric.replace(dateReg, "").trim();
        this.lyricItems[index] = {
          date: eachtime,
          currentMin: min,
          currentSec: sec,
          lyric: eachlyric,
        };
      }
    });
  }
  // 返回上一页
  back() {
    this.$router.go(-1);
  }
  // 改变当前播放进度
  setProgress(value: number) {
    const currentTime = (value * this.fullTimeInfo.fullTime) / 100;
    const currentMin = Math.floor(currentTime / 60)
      .toString()
      .padStart(2, "0");
    const currentSec = Math.floor(currentTime % 60)
      .toString()
      .padStart(2, "0");
    const info: CurrentTimeInfo = {
      currentTime,
      currentMin,
      currentSec,
      value1: value,
    };
    // 改变播放器进度
    AudioAction.next({ currentTimeInfo: info });
  }
  closeBottomSheet() {
    this.bottomSheetShow = false;
  }
  openBottomSheet() {
    this.bottomSheetShow = true;
  }
  deleteMusic(id: CommonIdType) {
    this.deleteFromMusicList(id);
    if (this.nowMusic?.id === id) {
      this.next();
    }
  }
  // 点击播放音乐
  changeMusic(index: number, id: CommonIdType) {
    // console.log(index)
    this.$api.getMusicUrl(id).then((musicList) => {
      // 下一首歌曲的url
      const url = musicList[0].url;
      const { name, artists, imgUrl } = this.musicUrlList[index];
      const info: CurrentMusic = {
        id,
        index,
        nowMusicUrl: url,
        nowName: name,
        nowArtists: artists,
        nowImgUrl: imgUrl,
      };
      // this.$router.push({path: `/music/${id}`})
      this.setIsPlaying(true);
      this.setCurrentMusicInfo(info);
    });
  }
}
</script>

<style lang="scss" scoped>
@mixin element-center {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.music-audio-wrap {
  .mask {
    width: 100%;
    height: 100%;
    overflow: hidden;
    position: fixed;
    left: 0;
    top: 0;
    z-index: -1;
    background-color: #444;
    .music-bg {
      position: absolute;
      top: 0;
      left: 0;
      bottom: 0;
      right: 0;
      height: 100%;
      width: 100%;
      filter: blur(1.2rem);
      background-position: center;
      background-repeat: no-repeat;
      background-size: cover;
      z-index: -2;
    }
  }
  > header {
    display: flex;
    height: 1rem;
    .header-iconback {
      width: 0.55rem;
      display: flex;
      justify-content: center;
      align-items: center;
      color: #fff9e8;
    }
    .header-title {
      flex: 1;
      @include element-center;
      .header-music-name {
        font-size: 0.25rem;
        color: #fff9e8;
      }
      .header-music-artists {
        font-size: 0.12rem;
        color: #665a3b;
      }
    }
  }
  .bar-line {
    display: block;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 0.05rem;
    background: radial-gradient(#d3d3d3 -90%, transparent 100%);
  }
  .music-main {
    .music-main-stick {
      display: block;
      height: 1.2rem;
      margin: 0 auto;
      margin-top: -0.05rem;
      margin-bottom: -0.2rem;
    }
    .music-main-pic {
      background: url(../../assets/imgs/cd_wrapper.png);
      background-size: cover;
      margin: 0 auto;
      width: 4rem;
      height: 4rem;
      display: flex;
      justify-content: center;
      align-items: center;
      animation: rotate 25s linear infinite;
      // animation-play-state: paused;
      img {
        width: 66%;
        margin: 0 auto;
        border-radius: 50%;
      }
    }
  }
  .music-section-icon {
    display: flex;
    justify-content: space-around;
    width: 80%;
    margin: 0.7rem auto 0.4rem;
    color: #fff;
    font-size: 0.4rem;
  }
  .music-section-time {
    display: flex;
    width: 80%;
    margin: 0 auto;
    color: #fff;
    .slider {
      margin-left: 0.2rem;
      margin-right: 0.2rem;
    }
  }
  .lyric-content {
    height: 0.2rem;
    width: 100%;
    text-align: center;
  }
  .music-section-contro {
    display: flex;
    color: #fff;
    margin: 0.5rem 0;
    height: 1rem;
    line-height: 1rem;
    > span {
      flex: 1;
      text-align: center;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 0.4rem;
    }
    .icon-play,
    .icon-pause {
      font-size: 0.7rem;
    }
    .play-model-icon.active {
      color: rgb(33, 150, 243);
    }
    > span {
      flex: 1;
      text-align: center;
    }
  }
}
@keyframes rotate {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
</style>

function
  // 获取歌词
  getLyric(id: any, CommonIdType: any) {
    throw new Error("Function not implemented.");
}
